﻿using System;
using System.Collections.Generic;
using NLite.Reflection;
using System.Reflection;
using NLite.Validation;
using NLite.Validation.DataAnnotations;
using NLite.Internal;

namespace NLite.Mapping.Internal
{
   
    abstract class MapperBase : IMapper
    {

        protected void FilterMembers(ref object from,ref object to)
        {
            foreach (var item in _Info.memberMappings)
                item.Key.Set(to, item.Value.DynamicInvoke(from));
        }
        
        protected readonly string Key;
        internal MapperInfo _Info;
        public IErrorState State { get; internal set; }

        protected MapperBase(Type fromType, Type toType)
        {
            Key = fromType.FullName + "->" + toType.FullName;
            State = new ErrorState();
            _Info = new MapperInfo
            {
                From = fromType
                ,To = toType
                ,Key = this.Key
            };
        }

        internal static bool IsPrimitiveTypeMapping(Type fromType, Type toType)
        {
            if (fromType == null)
                return false;
            if (toType == null)
                return false;
            if (fromType.IsNullable())
                fromType = fromType.GetGenericArguments()[0];
            if (Type.GetTypeCode(fromType) == TypeCode.Object)
                return false;
            if (toType.IsNullable())
                toType = toType.GetGenericArguments()[0];
            if (Type.GetTypeCode(toType) == TypeCode.Object)
                return false;

            return true;
        }

        public IMapperInfo Info { get { return _Info; } }

        public abstract void Map(ref object from, ref object to);

        protected void AddErrorState(string member, Exception ex)
        {
            State.AddError(member, ex.GetExceptionMessage());
        }

    }
}
